Skip to content

Fix a deadlock situation for BlockOnSplit test case. - #36226

Merged
jrmccluskey merged 1 commit into
apache:masterfrom
shunping:issue-36224
Sep 22, 2025
Merged

Fix a deadlock situation for BlockOnSplit test case.#36226
jrmccluskey merged 1 commit into
apache:masterfrom
shunping:issue-36224

Conversation

@shunping

Copy link
Copy Markdown
Collaborator

A deadlock can occur in the TestDynamicSplit/BlockOnSplit test case due to a race condition between two go routines, the processPlan and splitPlan goroutines:

  • processPlan - This is the routine where ProcessElement, GetRestriction and TryClaim are called.
    func (fn *splitTestSdf) ProcessElement(rt *splitTestRTracker, _ int, emit func(offsetrange.Restriction, int)) {
  • splitPlan - This is the routine where TrySplit is called.

The splitBlockingDriver uses channels for synchronization.

<-rt.split
// Start processing and start a claim, that'll be waiting for the mutex.
<-sdf.proc
<-rt.claim

However, a specific execution order can lead to a deadlock:

This creates a circular dependency and a deadlock. This change resolves the issue by moving the signal on rt.blockSplit to before the mutex is locked, preventing the deadlock.

fixes #36224

@github-actions github-actions Bot added the go label Sep 21, 2025
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @shunping, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical deadlock scenario identified in the TestDynamicSplit/BlockOnSplit test case. The deadlock stemmed from a specific timing issue where two goroutines, processPlan and splitPlan, contended for a shared mutex while waiting on each other's signals. By carefully reordering the mutex acquisition and channel signaling within the splitTestRTracker's TryClaim and TrySplit methods, this change eliminates the circular dependency, ensuring the test case can execute reliably without encountering the previously observed deadlock.

Highlights

  • Deadlock Resolution: Addresses a deadlock in the TestDynamicSplit/BlockOnSplit test case caused by a race condition between processPlan and splitPlan goroutines. The issue arose when TrySplit acquired a mutex and blocked, while ProcessElement simultaneously attempted to acquire the same mutex, leading to a circular dependency.
  • Synchronization Logic Adjustment: The fix involves reordering operations within the splitTestRTracker's TryClaim and TrySplit methods. Specifically, the rt.blockSplit signal is now sent before acquiring the rt.mu mutex, which effectively breaks the circular dependency and prevents the deadlock.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@shunping shunping self-assigned this Sep 21, 2025
@github-actions

Copy link
Copy Markdown
Contributor

Assigning reviewers:

R: @jrmccluskey for label go.

Note: If you would like to opt out of this review, comment assign to next reviewer.

Available commands:

  • stop reviewer notifications - opt out of the automated review tooling
  • remind me after tests pass - tag the comment author after tests pass
  • waiting on author - shift the attention set back to the author (any comment or push by the author will return the attention set to the reviewers)

The PR bot will only process comments in the main thread (not review comments).

@jrmccluskey jrmccluskey left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@jrmccluskey
jrmccluskey merged commit 9146029 into apache:master Sep 22, 2025
6 checks passed
@shunping

Copy link
Copy Markdown
Collaborator Author

FYI, I ran the test 1000x with race detector and could not see a stuck test.

go test -v -race -count=1000 github.com/apache/beam/sdks/v2/go/pkg/beam/core/runtime/exec -run TestDynamicSplit/BlockOnSplit

Previously, the test would get stuck when running 10x with race detector.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Failing Test]: TestDynamicSplit/BlockOnSplit in Go Precommit Test in Flaky

2 participants